#include "WindowsSerialPort.h"
#include <iostream>

using namespace MC500;
using namespace std;

WinSerialPort::WinSerialPort(const std::string &devName) : SerialPort(), devName_(devName), comHandle_(INVALID_HANDLE_VALUE){

                                                                                            };

WinSerialPort::~WinSerialPort()
{
    if (comHandle_ == INVALID_HANDLE_VALUE)
    {
        CloseHandle(comHandle_);
    }
}

ErrorCode WinSerialPort::Init(uint32_t speed)
{
    comHandle_ = CreateFile(devName_.c_str(), GENERIC_READ| GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (comHandle_ == INVALID_HANDLE_VALUE)
    {
        cout << "Open serial port failed!" << endl;
        return MC500_ERROR_NOT_SUCH_DEVICE;
    }

    //配置缓冲区大小
    if (!SetupComm(comHandle_, 1024, 1024))
    {
        cout << "SetupComm failed!" << endl;
        return MC500_ERROR_CONFIG_COM_FAILED;
    }

    DCB dcb; /* 串口状态信息 */

        if (::GetCommState(comHandle_, &dcb) == 0) /*判断串口信息是否获取情况*/
        {
            cout << "GetCommState failed!err=" << GetLastError() << endl;
            return MC500_ERROR_GET_COM_STATUS;
        }
    
        // CBR_9600
        dcb.BaudRate = speed;
        dcb.ByteSize = 8;
        dcb.Parity = NOPARITY;     /*指定奇偶校验位*/
        dcb.StopBits = ONESTOPBIT; /*指定停止位的位数*/
        //m_dcb.fParity = fParity;  /*指定奇偶校验位*/

        if (SetCommState(comHandle_, &dcb) == 0)
        {
            return MC500_ERROR_CONFIG_COM_FAILED;
        }
    

    COMMTIMEOUTS timeouts = {0};
    timeouts.ReadIntervalTimeout = 50;         // in milliseconds
    timeouts.ReadTotalTimeoutConstant = 50;    // in milliseconds
    timeouts.ReadTotalTimeoutMultiplier = 10;  // in milliseconds
    timeouts.WriteTotalTimeoutConstant = 50;   // in milliseconds
    timeouts.WriteTotalTimeoutMultiplier = 10; // in milliseconds
    if(!SetCommTimeouts(comHandle_, &timeouts)){
        return MC500_ERROR_CONFIG_COM_FAILED;
    }

    PurgeComm(comHandle_, PURGE_RXCLEAR | PURGE_TXCLEAR);

    DWORD dwError;
    COMSTAT cs;
    if (!ClearCommError(comHandle_, &dwError, &cs))
    {
        std::cout << "Clear error failed!" << std::endl;
        CloseHandle(comHandle_);
        return MC500_ERROR_CLEAR_COM_ERROR;
    }

    return MC500_SUCCESS;
}

//发送数据
ErrorCode WinSerialPort::Send(const uint8_t *data, uint16_t len)
{
    long unsigned int writeLen = 0;
    if (!WriteFile(comHandle_, (const char *)data, len, &writeLen, nullptr))
    {
        DWORD dwRet = GetLastError();
        return dwRet;
    }

    return 0;
}

//接受数据
ErrorCode WinSerialPort::Read(uint8_t *data, uint16_t buffSize, uint16_t &readCount)
{
    long unsigned int readLen = 0;
    if (!ReadFile(comHandle_, data, buffSize, &readLen, nullptr))
    {
        DWORD dwRet = GetLastError();
        return dwRet;
    }
    readCount = (uint16_t)readLen;
    return 0;
}